package security.config;/**
 * @Auther: liyipeng
 * @Date: 2020/1/9 14:47
 * @Description:
 */

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.filter.CorsFilter;
import security.SecurityUtil.jwt.JwtAuthenticationProvider;
import security.SecurityUtil.login.CustomUserDetailService;
import security.SecurityUtil.login.MySha1PasswordEncoder;
import security.SecurityUtil.login.MyUsernamePasswordAuthenticationFilter;
import security.handler.JsonLoginSuccessHandler;
import security.handler.JwtRefreshSuccessHandler;

import java.util.Arrays;

/**
 * <p>类名: WebSecurityConfig</p>
 * <p>描述:TODO</p>
 * <p>创建人: liyp</p>
 * <p>创建时间: 2020/1/9 14:47</p>
 * <p>@version 2.0  </p>
 * <p>修改内容: ......</p>
 * <p>修改说明: ......</p>
 * <p>修改时间: ......</p>
 * <p>修改人: ......</p>
 * <p>每次修改，请增加上述修改信息说明</>
 */
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    CustomUserDetailService customUserDetailService;

    @Autowired
    JsonLoginSuccessHandler jsonLoginSuccessHandler;

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/image/**","/swagger/**","/swagger*/**","/webjars/**", "/v2/**","/login","/actuator/**")
                .permitAll() //静态资源访问无需认证
                .anyRequest().authenticated()  //默认其它的请求都需要认证，这里一定要添加
                .and()
                .csrf().disable()  //CRSF禁用，因为不使用session
                .sessionManagement().disable()  //禁用session
                .formLogin().disable()
                .cors()  //支持跨域
                .and()   //添加header设置，支持跨域和ajax请求
                .headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
                new Header("Access-control-Allow-Origin","*"),
                new Header("Access-Control-Expose-Headers","Authorization"))))
                .and()//.addFilterAfter(myUsernamePasswordAuthenticationFilter(),LogoutFilter.class)
                //拦截OPTIONS请求，直接返回header
                      .addFilterAfter(new OptionsRequestFilter(), CorsFilter.class)
                .apply(new JsonLoginConfigurer<>()).loginSuccessHandler(jsonLoginSuccessHandler)
                .and()
                //添加token的filter
                .apply(new JwtLoginConfigurer<>()).tokenValidSuccessHandler(jwtRefreshSuccessHandler()).permissiveRequestUrls("/logout")
                .and()
                //使用默认的logoutFilter
                .logout()
                //默认就是"/logout"
               .logoutUrl("/logout")
//                .addLogoutHandler(tokenClearLogoutHandler())  //logout时清除token
                //logout成功后返回200
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
                .and()
                .sessionManagement().disable();
    }
    //配置provider
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider()).authenticationProvider(jwtAuthenticationProvider());
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public JwtRefreshSuccessHandler jwtRefreshSuccessHandler(){
        return new JwtRefreshSuccessHandler(customUserDetailService);
    }

    @Bean
    public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter()throws Exception{
        MyUsernamePasswordAuthenticationFilter filter = new MyUsernamePasswordAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }
    @Bean("jwtAuthenticationProvider")
    protected AuthenticationProvider jwtAuthenticationProvider() {
        return new JwtAuthenticationProvider(customUserDetailService);
    }

   @Bean
   public PasswordEncoder mySha1PasswordEncoder(){
       return new MySha1PasswordEncoder();
   }

    @Bean("daoAuthenticationProvider")
    protected AuthenticationProvider daoAuthenticationProvider() throws Exception{
        //这里会默认使用BCryptPasswordEncoder比对加密后的密码，注意要跟createUser时保持一致
        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
        daoProvider.setUserDetailsService(customUserDetailService);
        daoProvider.setPasswordEncoder(mySha1PasswordEncoder());
        return daoProvider;
    }
}